#include <context.h>
#include <fmt.h>
#include <riscv.h>

/* 指向下一个进程的 trapframe */
extern void switch_to(context_t *next);

uint8_t __attribute__((aligned(16))) task_stack[MAX_TASKS][STACK_SIZE];
context_t task_context[MAX_TASKS];

static int _top = 0;
static int _current = -1;

static void w_sscratch(uintptr_t x) { asm volatile("csrw sscratch, %0" : : "r" (x)); }
static void inline schedule();

void sched_init() {
    write_csr(sscratch, 0);
    printf("++ sched init\n");
}

int task_create(void (*proc_fn)(void)) {
    if (_top < MAX_TASKS) {
        task_context[_top].sp = (uintptr_t) &task_stack[_top][STACK_SIZE];
        task_context[_top].ra = (uintptr_t) proc_fn;
        _top ++;
        return 0;
    } else {
        return -1;
    }
}

void task_yield() {
    schedule();
}

static void inline schedule()
{
    if (_top <= 0) {
        printf("No tasks to schedule!\n");
        return;
    }
	_current = (_current + 1) % _top;
    context_t *next = &(task_context[_current]);
	switch_to(next);
}